/*
 * Copyright (C) 2021 The Chinese Software International Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.azoft.carousellayoutmanager;

import ohos.agp.components.*;

import static com.azoft.carousellayoutmanager.Constant.*;

import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.multimodalinput.event.TouchEvent;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * 布局管理器
 *
 * @since 2021-03-25
 */
public class CarouselLayoutManager extends StackLayout implements Component.TouchEventListener,
        Component.EstimateSizeListener {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");
    /**
     * visibleMaxNum 显示的最大数量
     */
    private static final int VISIBLE_MAX_NUM = 9;
    /**
     * centerMargin 上下左右的间距
     */
    private static final int CENTER_MARGIN = 50;
    /**
     * adapter的实现类
     */
    private CustomAdapterImp customAdapterImp;
    /**
     * 全部的数据
     */
    private List<Component> dataComponents = new ArrayList<>();
    /**
     * 已经添加的数据
     */
    private List<Component> addComponents = new ArrayList<>();
    /**
     * 水平方向占位的数据
     */
    private List<Component> blankComponents = new ArrayList<>();
    /**
     * 垂直方向
     */
    private boolean isLayoutVertical;
    /**
     * 水平方向
     */
    private boolean isLayoutHorizontal;

    /**
     * Y滑动的位置
     */
    private float oldY;
    /**
     * X滑动的位置
     */
    private float oldX;

    /**
     * widthSize 宽度
     */
    private int widthSize;
    /**
     * heightSize 高度
     */
    private int heightSize;
    /**
     * orientation 方向
     */
    private int orientation;
    /**
     * 每一个子item的宽
     */
    private float[] childWidth;
    /**
     * 每一个子item的高
     */
    private float[] childHeight;
    /**
     * 第一个空白的component
     */
    private Component firstBlackComponent;
    /**
     * 最后一个空白的component
     */
    private Component lastBlackComponent;
    /**
     * 速度控制器
     */
    private VelocityDetector velocityDetector = null;
    /**
     * 相当与线程
     */
    private TaskDispatcher taskDispatcher;
    /**
     * 循环线程的running接口
     */
    private EndOrStartRunning endOrStartRunning;
    /**
     * 水平方向  边界
     */
    private boolean isHorizontalBoundary = false;
    /**
     * 垂直向下
     */
    private boolean isVerticalBottom = false;
    /**
     * 垂直向上
     */
    private boolean isVerticalTop = false;
    /**
     * 水平向左
     */
    private boolean isHorizontalLeft = false;
    /**
     * 水平向右
     */
    private boolean isHorizontalRight = false;
    /**
     * 下面按钮是向后还是向前
     */
    private boolean isBack = false;

    /**
     * 构造方法
     *
     * @param context 上下文
     * @param attrSet 额外参数
     */
    public CarouselLayoutManager(Context context, AttrSet attrSet) {
        super(context, attrSet);
        setTouchEventListener(this);
        setEstimateSizeListener(this);
        if (velocityDetector == null) {
            velocityDetector = VelocityDetector.obtainInstance();
        }
        if (endOrStartRunning == null) {
            endOrStartRunning = new EndOrStartRunning();
        }
        if (taskDispatcher == null) {
            taskDispatcher = context.getUITaskDispatcher();
        }
    }

    /**
     * 设置数据源
     *
     * @param customAdapterImp adapter实现类
     */
    public void setAdapter(CustomAdapterImp customAdapterImp) {
        this.customAdapterImp = customAdapterImp;
        int countNum = customAdapterImp == null ? 0 : customAdapterImp.getCount();
        for (int jj = 0; jj < countNum; jj++) {
            Component component = customAdapterImp.getComponent(jj, null);
            dataComponents.add(component);
        }
        addComponents.clear();
        if (getOrientation() == Component.HORIZONTAL) {
            for (int ii = 0; ii < VISIBLE_MAX_NUM / INDEX; ii++) {
                Component component = getBlankData();
                ((Text) (component.findComponentById(ResourceTable.Id_text))).setText(ii);
                blankComponents.add(component);
            }
            firstBlackComponent = blankComponents.get(0);
            addComponents.addAll(blankComponents);
            addComponents.addAll(dataComponents.subList(0, VISIBLE_MAX_NUM - blankComponents.size()));
        } else if (getOrientation() == Component.VERTICAL) {
            addComponents.addAll(dataComponents.subList(dataComponents.size() - Constant.CENTER_INDEX,
                    dataComponents.size()));
            addComponents.addAll(dataComponents.subList(0, VISIBLE_MAX_NUM - Constant.CENTER_INDEX));
        }
        invalidate();
    }

    @Override
    public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
        widthSize = EstimateSpec.getSize(widthEstimateConfig);
        heightSize = EstimateSpec.getSize(heightEstimateConfig);
        onMeasure();
        if (getOrientation() == Component.VERTICAL) {
            onLayoutVertical();
        } else if (getOrientation() == Component.HORIZONTAL) {
            onLayoutHorizontal();
        }
        return false;
    }

    /**
     * 水平位置
     */
    private void onLayoutHorizontal() {
        if (isLayoutHorizontal) {
            return;
        }
        isLayoutHorizontal = true;
        removeAllComponents();
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        float tempTranslationX;
        Component component;
        for (int ii = 0; ii <= centerNum; ii++) {
            if (ii < centerNum) {
                component = addComponents.get(ii);
                addComponentHorizontal(component, childHeight[ii], false);
                tempTranslationX = CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * ii;
                component.setTranslationX(tempTranslationX);

                component = addComponents.get(VISIBLE_MAX_NUM - ii - 1);
                addComponentHorizontal(component, childHeight[VISIBLE_MAX_NUM - ii - 1], false);
                tempTranslationX = CENTER_MARGIN
                        + CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * (Constant.SEVEN_INDEX - ii);
                component.setTranslationX(tempTranslationX);
            } else {
                component = addComponents.get(centerNum);
                addComponentHorizontal(component, childHeight[centerNum], false);
                tempTranslationX = CENTER_MARGIN;
                component.setTranslationX(tempTranslationX);
            }
        }
    }

    /**
     * 垂直位置
     */
    private void onLayoutVertical() {
        if (isLayoutVertical) {
            return;
        }
        isLayoutVertical = true;
        removeAllComponents();
        int centerNum = VISIBLE_MAX_NUM / INDEX;

        float tempTranslationY;

        Component component;

        for (int ii = 0; ii <= centerNum; ii++) {
            if (ii < centerNum) {
                component = addComponents.get(ii);
                addComponentVertical(component, childWidth[ii], false);
                tempTranslationY = CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * ii;
                component.setTranslationY(tempTranslationY);
                component = addComponents.get(VISIBLE_MAX_NUM - ii - 1);
                addComponentVertical(component, childWidth[VISIBLE_MAX_NUM - ii - 1], false);
                tempTranslationY = CENTER_MARGIN
                        + CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * (Constant.SEVEN_INDEX - ii);
                component.setTranslationY(tempTranslationY);
            } else {
                component = addComponents.get(centerNum);
                addComponentVertical(component, childWidth[centerNum], false);
                tempTranslationY = CENTER_MARGIN;
                component.setTranslationY(tempTranslationY);
            }
        }
    }

    /**
     * 测量子item的宽高
     */
    private void onMeasure() {
        childWidth = new float[VISIBLE_MAX_NUM];
        childHeight = new float[VISIBLE_MAX_NUM];
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        int startWidth = widthSize / INDEX;
        int startHeight = heightSize / INDEX;
        for (int ii = 0; ii <= centerNum; ii++) {
            if (ii < centerNum) {
                childWidth[ii] = startWidth + (widthSize - startWidth) / centerNum * ii;
                childWidth[VISIBLE_MAX_NUM - ii - 1] = childWidth[ii];
                childHeight[ii] = startHeight + (heightSize - startHeight) / centerNum * ii;
                childHeight[VISIBLE_MAX_NUM - ii - 1] = childHeight[ii];
            } else {
                childWidth[centerNum] = widthSize;
                childHeight[centerNum] = heightSize;
            }
        }
    }

    /**
     * 在水平方向时前面需要四个空白占位
     *
     * @return Component
     */
    private Component getBlankData() {
        return LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_blank_item_view, null, false);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
            touchDown(touchEvent);
            return true;
        }
        switch (touchEvent.getAction()) {
            case TouchEvent.OTHER_POINT_DOWN:
            case TouchEvent.PRIMARY_POINT_DOWN:
                touchDown(touchEvent);
                break;
            case TouchEvent.POINT_MOVE:
                if (getOrientation() == Component.VERTICAL) {
                    scrolledVertical(touchEvent);
                } else if (getOrientation() == Component.HORIZONTAL) {
                    scrolledHorizontal(touchEvent);
                }
                oldX = touchEvent.getPointerPosition(0).getX();
                oldY = touchEvent.getPointerPosition(0).getY();
                break;
            case TouchEvent.OTHER_POINT_UP:
            case TouchEvent.PRIMARY_POINT_UP:
                velocityDetector.addEvent(touchEvent);
                velocityDetector.calculateCurrentVelocity(Constant.PIXEL_1500);
                if (getOrientation() == Component.VERTICAL
                        && velocityDetector.getVerticalVelocity() > Constant.PIXEL_500) {
                    rapidBottomSlide();
                }
                if (getOrientation() == Component.VERTICAL
                        && velocityDetector.getVerticalVelocity() < 0
                        && Math.abs(velocityDetector.getVerticalVelocity()) > Constant.PIXEL_500) {
                    rapidTopSlide();
                }
                if (getOrientation() == Component.HORIZONTAL
                        && velocityDetector.getHorizontalVelocity() > Constant.PIXEL_500) {
                    rapidRightSlide();
                }
                if (getOrientation() == Component.HORIZONTAL
                        && velocityDetector.getHorizontalVelocity() < 0
                        && Math.abs(velocityDetector.getHorizontalVelocity()) > Constant.PIXEL_500) {
                    rapidLeftSlide();
                }
            case TouchEvent.CANCEL:
            case TouchEvent.NONE:
                oldX = 0;
                oldY = 0;
                if (getOrientation() == Component.VERTICAL) {
                    setAgainVerticalTranslationX();
                    setAgainVerticalTranslationY();
                } else if (getOrientation() == Component.HORIZONTAL) {
                    setAgainHorizontalTranslationX();
                    setAgainHorizontalTranslationY();
                }
                velocityDetector.clear();
                break;
            default:
                break;
        }
        return false;
    }

    private void touchDown(TouchEvent touchEvent){
        oldX = touchEvent.getPointerPosition(0).getX();
        oldY = touchEvent.getPointerPosition(0).getY();
        if (velocityDetector == null) {
            velocityDetector = VelocityDetector.obtainInstance();
        } else {
            velocityDetector.clear();
        }
        velocityDetector.addEvent(touchEvent);
    }
    /**
     * 快速左滑
     */
    private void rapidLeftSlide() {
        isBack = true;
        isHorizontalLeft = true;
        isHorizontalBoundary = true;
        SecureRandom random = new SecureRandom();
        int index = random.nextInt(Constant.RANDOM_INDEX) + 1;
        HiLog.error(LABEL, "index>>>>%{public}s" + index);
        int center = getIndex();
        if (center == dataComponents.size() - 1 || center == index) {
            return;
        } else {
            index = Math.min(center + index, dataComponents.size() - 1);
        }
        if (index == center) {
            return;
        }
        sendRunnable(index, true);
    }

    /**
     * 快速右滑
     */
    private void rapidRightSlide() {
        isBack = false;
        isHorizontalRight = true;
        isHorizontalBoundary = false;
        SecureRandom random = new SecureRandom();
        int index = random.nextInt(Constant.RANDOM_INDEX) + 1;
        HiLog.error(LABEL, "index111>>>>" + index);

        int center = getIndex();
        if (center == 0 || center == index) {
            return;
        } else {
            index = Math.max(center - index, 0);
        }
        if (index == center) {
            return;
        }
        HiLog.error(LABEL, "index>>>>%{public}s" + index);
        sendRunnable(index, true);
    }

    /**
     * 快速上滑
     */
    private void rapidTopSlide() {
        isBack = false;
        isVerticalTop = true;
        SecureRandom random = new SecureRandom();
        int index = random.nextInt(Constant.RANDOM_INDEX) + 1;
        HiLog.error(LABEL, "index>>>>" + index);
        int center = getIndex();
        if (center + index > dataComponents.size() - 1) {
            index = center + index - dataComponents.size();
        } else {
            index = center + index;
        }
        sendRunnable(index, true);
    }

    /**
     * 快速下滑
     */
    private void rapidBottomSlide() {
        isBack = true;
        isVerticalBottom = true;
        SecureRandom random = new SecureRandom();
        int index = random.nextInt(Constant.RANDOM_INDEX) + 1;
        HiLog.error(LABEL, "index>>>>" + index);
        int center = getIndex();
        if (center - index < 0) {
            index = dataComponents.size() - index;
        } else {
            index = center - index;
        }
        sendRunnable(index, true);
    }

    /**
     * 水平滑动
     *
     * @param touchEvent TouchEvent事件
     */
    private void scrolledHorizontal(TouchEvent touchEvent) {
        if (Math.abs(touchEvent.getPointerPosition(0).getX() - oldX) < FIVE_INDEX) {
            return;
        }

        if (addComponents.contains(firstBlackComponent) && touchEvent.getPointerPosition(0).getX() > oldX) {
            return;
        }

        if (lastBlackComponent != null && addComponents.contains(lastBlackComponent)
                && touchEvent.getPointerPosition(0).getX() < oldX) {
            return;
        }

        if (touchEvent.getPointerPosition(0).getX() > oldX) {
            scrolledRightHorizontal(Constant.INVALID, false);
        } else if (touchEvent.getPointerPosition(0).getX() < oldX) {
            scrolledLeftHorizontal(Constant.INVALID, false);
        }
    }

    private void scrolledRightHorizontal(int startIndex, boolean isStartOrStop) {
        boolean isStop = true;
        if (isStartOrStop) {
            isStop = false;
        }
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component leftComponent;
        Component rightComponent;
        for (int ii = 0; ii <= centerNum; ii++) {
            leftComponent = ii - 1 < 0 ? null : addComponents.get(ii - 1);
            rightComponent = addComponents.get(VISIBLE_MAX_NUM - 1 - ii);
            rightComponent.setScaleY(rightComponent.getScaleY() - SCALE_FIVE_Y);
            rightComponent.setTranslationX(rightComponent.getTranslationX() + 1);
            if (leftComponent != null) {
                leftComponent.setScaleY(leftComponent.getScaleY() + SCALE_FIVE_Y);
                leftComponent.setTranslationX(leftComponent.getTranslationX() - SCALE_EIGHT_Y);
                if (leftComponent.getScaleY() * leftComponent.getHeight()
                        >= rightComponent.getHeight() * rightComponent.getScaleY()) {
                    moveChildToFront(leftComponent);
                    Component start = addComponents.get(0);
                    int tempIndex;
                    if (blankComponents.contains(start)) {
                        tempIndex = blankComponents.indexOf(start);
                        if (tempIndex - 1 < 0) {
                            addComponents.add(0, dataComponents.get(dataComponents.size() - 1));
                        } else {
                            addComponents.add(0, blankComponents.get(tempIndex - 1));
                        }
                    } else {
                        tempIndex = dataComponents.indexOf(start);
                        if (tempIndex - 1 < 0) {
                            addComponents.add(0, blankComponents.get(blankComponents.size() - 1));
                            firstBlackComponent = blankComponents.get(0);
                            lastBlackComponent = null;
                        } else {
                            addComponents.add(0, dataComponents.get(tempIndex - 1));
                        }
                    }
                    removeComponent(addComponents.get(addComponents.size() - 1));
                    addHorizontalRightLatest();
                    addComponents.remove(addComponents.size() - 1);
                    setAgainHorizontalTranslationY();
                    setAgainHorizontalTranslationX();
                    if (addComponents.contains(leftComponent)
                            && startIndex == dataComponents.indexOf(leftComponent) && isStartOrStop) {
                        isStop = true;
                        break;
                    }
                }
            }
        }
        if (!isStop) {
            cycle();
        } else {
            isHorizontalRight = false;
        }
    }

    /**
     * 添加最新的一个（水平向右方向）
     */
    private void addHorizontalRightLatest() {
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        int index = 0;
        float tempTranslationX = CENTER_MARGIN * 1f / centerNum;
        Component component = addComponents.get(index);
        addComponentHorizontal(component, childWidth[index], true);
        component.setTranslationX(tempTranslationX);
    }

    /**
     * 水平向左滑动
     *
     * @param endIndex      结束的下标
     * @param isStartOrStop 开始还是结束
     */
    private void scrolledLeftHorizontal(int endIndex, boolean isStartOrStop) {
        boolean isStop = true;
        if (isStartOrStop) {
            isStop = false;
        }
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component leftComponent;
        Component rightComponent;
        for (int ii = 0; ii <= centerNum; ii++) {
            leftComponent = addComponents.get(ii);
            rightComponent = VISIBLE_MAX_NUM - ii == addComponents.size() ? null
                    : addComponents.get(VISIBLE_MAX_NUM - ii);
            leftComponent.setScaleY(leftComponent.getScaleY() - SCALE_FIVE_Y);
            leftComponent.setTranslationX(leftComponent.getTranslationX() - 1);
            if (rightComponent != null) {
                rightComponent.setScaleY(rightComponent.getScaleY() + SCALE_FIVE_Y);
                rightComponent.setTranslationX(rightComponent.getTranslationX() - SCALE_EIGHT_Y);
                if (rightComponent.getHeight() * rightComponent.getScaleY() >= leftComponent.getScaleY()
                        * leftComponent.getHeight()) {
                    moveChildToFront(rightComponent);
                    Component end = addComponents.get(VISIBLE_MAX_NUM - 1);
                    int tempIndex = dataComponents.indexOf(end);
                    if (blankComponents.contains(end)) {
                        tempIndex = blankComponents.indexOf(end);
                        if (tempIndex + 1 > blankComponents.size() - 1) {
                            addComponents.add(dataComponents.get(0));
                        } else {
                            addComponents.add(blankComponents.get(tempIndex + 1));
                        }
                    } else {
                        if (tempIndex + 1 > dataComponents.size() - 1) {
                            addComponents.add(blankComponents.get(0));
                            lastBlackComponent = blankComponents.get(blankComponents.size() - 1);
                            firstBlackComponent = null;
                        } else {
                            addComponents.add(dataComponents.get(tempIndex + 1));
                        }
                    }
                    removeComponent(addComponents.get(0));
                    addHorizontalLatest();
                    addComponents.remove(0); // 移除顶部
                    setAgainHorizontalTranslationY();
                    setAgainHorizontalTranslationX();
                    if (addComponents.contains(rightComponent)
                            && endIndex == dataComponents.indexOf(rightComponent) && isStartOrStop) {
                        isStop = true;
                        break;
                    }
                }
            }
        }
        if (!isStop) {
            cycle();
        } else {
            isHorizontalLeft = false;
        }
    }

    /**
     * 水平方向平移Y轴
     */
    private void setAgainHorizontalTranslationY() {
        for (int ii = 0; ii < addComponents.size(); ii++) {
            Component tempCom = addComponents.get(ii);
            tempCom.setHeight((int) (childHeight[ii]));
            tempCom.setScaleY(1);
            float tempTranslationY = (heightSize - childHeight[ii]) / INDEX;
            tempCom.setTranslationY(tempTranslationY);
        }
    }

    private void scrolledTopVertical(int startIndex, boolean isStartOrStop) {
        boolean isStop = true;
        if (isStartOrStop) {
            isStop = false;
        }
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component topView;
        Component bottomView;
        for (int ii = 0; ii <= centerNum; ii++) {
            topView = addComponents.get(ii);
            bottomView = VISIBLE_MAX_NUM - ii == addComponents.size() ? null : addComponents.get(
                    VISIBLE_MAX_NUM - ii);
            topView.setScaleX(topView.getScaleX() - SCALE_FIVE_Y);
            topView.setTranslationY(topView.getTranslationY() - SCALE_NINE_Y);
            if (bottomView != null) {
                bottomView.setScaleX(bottomView.getScaleX() + SCALE_FIVE_Y);
                bottomView.setTranslationY(bottomView.getTranslationY() - SCALE_SIX_Y);
                if (bottomView.getWidth() * bottomView.getScaleX() >= topView.getScaleX()
                        * topView.getWidth()) {
                    moveChildToFront(bottomView);
                    Component end = addComponents.get(VISIBLE_MAX_NUM - 1);
                    int tempIndex = dataComponents.indexOf(end);
                    tempIndex = tempIndex + 1 > dataComponents.size() - 1 ? 0 : tempIndex + 1;
                    addComponents.add(dataComponents.get(tempIndex));
                    removeComponent(addComponents.get(0));
                    addVerticalLatest();
                    addComponents.remove(0); // 移除顶部
                    setAgainVerticalTranslationX();
                    setAgainVerticalTranslationY();
                    if (addComponents.contains(bottomView)
                            && startIndex == dataComponents.indexOf(bottomView) && isStartOrStop) {
                        isStop = true;
                        break;
                    }
                }
            }
        }
        if (!isStop) {
            cycle();
        } else {
            isVerticalTop = false;
        }
    }

    private void scrolledBottomVertical(int endIndex, boolean isStartOrStop) {
        boolean isStop = true;
        if (isStartOrStop) {
            isStop = false;
        }
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component topView;
        Component bottomView;
        for (int ii = 0; ii <= centerNum; ii++) {
            topView = ii - 1 < 0 ? null : addComponents.get(ii - 1);
            bottomView = addComponents.get(VISIBLE_MAX_NUM - 1 - ii);
            bottomView.setScaleX(bottomView.getScaleX() - SCALE_FIVE_Y);
            bottomView.setTranslationY(bottomView.getTranslationY() + 1);
            if (topView != null) {
                topView.setScaleX(topView.getScaleX() + SCALE_FIVE_Y);
                topView.setTranslationY(topView.getTranslationY() - SCALE_FOUR_Y);
                if (topView.getWidth() * topView.getScaleX() >= bottomView.getScaleX()
                        * bottomView.getWidth()) {
                    moveChildToFront(topView);
                    Component start = addComponents.get(0);
                    int tempIndex = dataComponents.indexOf(start);
                    tempIndex = tempIndex - 1 < 0 ? dataComponents.size() - 1 : tempIndex - 1;
                    addComponents.add(0, dataComponents.get(tempIndex));
                    removeComponent(addComponents.get(addComponents.size() - 1));
                    addVerticalBottomLatest();
                    addComponents.remove(addComponents.size() - 1); // 移除顶部
                    setAgainVerticalTranslationX();
                    setAgainVerticalTranslationY();
                    if (addComponents.contains(topView)
                            && endIndex == dataComponents.indexOf(topView) && isStartOrStop) {
                        isStop = true;
                        break;
                    }
                }
            }
        }

        if (!isStop) {
            cycle();
        } else {
            isVerticalBottom = false;
        }
    }

    /**
     * 垂直方向进行平移x
     */
    private void setAgainVerticalTranslationX() {
        for (int ii = 0; ii < addComponents.size(); ii++) {
            Component tempCom = addComponents.get(ii);
            tempCom.setWidth((int) (childWidth[ii]));
            tempCom.setScaleX(1);
            float tempTranslationX = (widthSize - childWidth[ii]) / INDEX;
            tempCom.setTranslationX(tempTranslationX);
        }
    }

    /**
     * 垂直滑动
     *
     * @param touchEvent TouchEvent事件
     */
    private void scrolledVertical(TouchEvent touchEvent) {
        if (Math.abs(touchEvent.getPointerPosition(0).getY() - oldY) < FIVE_INDEX) {
            return;
        }
        if (touchEvent.getPointerPosition(0).getY() > oldY) {
            scrolledBottomVertical(Constant.INVALID, false);
        } else if (touchEvent.getPointerPosition(0).getY() < oldY) {
            scrolledTopVertical(Constant.INVALID, false);
        }
    }

    /**
     * 添加水平方向的Component
     *
     * @param component component
     * @param height    高度
     * @param isIndex   是否滑动添加
     */
    private void addComponentHorizontal(Component component, float height, boolean isIndex) {
        LayoutConfig mLayoutConfig = new LayoutConfig(widthSize - CENTER_MARGIN * INDEX,
                (int) height);
        component.setLayoutConfig(mLayoutConfig);

        if (component.getComponentParent() != null) {
            removeComponent(component);
        }
        if (isIndex) {
            addComponent(component, 0);
        } else {
            addComponent(component);
        }

        if (height != heightSize) {
            float tempTranslationY = (heightSize - height) / INDEX;
            component.setTranslationY(tempTranslationY);
        } else {
            component.setTranslationY(0);
        }
    }

    /**
     * 添加垂直方向的Component
     *
     * @param component component
     * @param width     宽度
     * @param isIndex   是否滑动添加
     */
    private void addComponentVertical(Component component, float width, boolean isIndex) {
        LayoutConfig mLayoutConfig = new LayoutConfig((int) width,
                getHeight() - CENTER_MARGIN * INDEX);

        component.setLayoutConfig(mLayoutConfig);

        if (component.getComponentParent() != null) {
            removeComponent(component);
        }

        if (isIndex) {
            addComponent(component, 0);
        } else {
            addComponent(component);
        }

        if (width != widthSize) {
            float tempTranslationX = (widthSize - width) / INDEX;
            component.setTranslationX(tempTranslationX);
        } else {
            component.setTranslationX(0);
        }
    }

    /**
     * 添加最新的一个（垂直方向）
     */
    private void addVerticalLatest() {
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component component = addComponents.get(VISIBLE_MAX_NUM - 1);
        addComponentVertical(component, childWidth[VISIBLE_MAX_NUM - 1], true);
        float tempTranslationY = CENTER_MARGIN + CENTER_MARGIN * 1f / centerNum * centerNum;
        component.setTranslationY(tempTranslationY);
    }

    /**
     * 添加最新的一个（垂直方向）
     */
    private void addVerticalBottomLatest() {
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component component = addComponents.get(0);
        addComponentVertical(component, childWidth[0], true);
        float tempTranslationY = CENTER_MARGIN * 1f / centerNum * centerNum;
        component.setTranslationY(tempTranslationY);
    }

    /**
     * 添加最新的一个（水平方向）
     */
    private void addHorizontalLatest() {
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        Component component = addComponents.get(VISIBLE_MAX_NUM - 1);
        addComponentHorizontal(component, childWidth[VISIBLE_MAX_NUM - 1], true);
        float tempTranslationX = CENTER_MARGIN + CENTER_MARGIN * 1f / centerNum * centerNum;
        component.setTranslationX(tempTranslationX);
    }

    /**
     * 重新Y轴的Translation（垂直方向）
     */
    private void setAgainVerticalTranslationY() {
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        float tempTranslationY;
        Component component;
        for (int ii = 0; ii <= centerNum; ii++) {
            if (ii < centerNum) {
                component = addComponents.get(ii);
                tempTranslationY = CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * ii;
                component.setTranslationY(tempTranslationY);
                component = addComponents.get(VISIBLE_MAX_NUM - ii - 1);
                tempTranslationY = CENTER_MARGIN
                        + CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * (Constant.SEVEN_INDEX - ii);
                component.setTranslationY(tempTranslationY);
            } else {
                component = addComponents.get(centerNum);
                tempTranslationY = CENTER_MARGIN;
                component.setTranslationY(tempTranslationY);
            }
        }
    }

    /**
     * 重新X轴的Translation（水平方向）
     */
    private void setAgainHorizontalTranslationX() {
        int centerNum = VISIBLE_MAX_NUM / INDEX;
        float tempTranslationX;
        Component component;
        for (int ii = 0; ii <= centerNum; ii++) {
            if (ii < centerNum) {
                component = addComponents.get(ii);
                tempTranslationX = CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * ii;
                component.setTranslationX(tempTranslationX);
                component = addComponents.get(VISIBLE_MAX_NUM - ii - 1);
                tempTranslationX = CENTER_MARGIN
                        + CENTER_MARGIN * 1f / Constant.SEVEN_INDEX * (Constant.SEVEN_INDEX - ii);
                component.setTranslationX(tempTranslationX);
            } else {
                component = addComponents.get(centerNum);
                tempTranslationX = CENTER_MARGIN;
                component.setTranslationX(tempTranslationX);
            }
        }
    }

    /**
     * 获取方向
     *
     * @return int数值的方向
     */
    public int getOrientation() {
        return orientation;
    }

    /**
     * 设置方向
     *
     * @param orientation int
     */
    public void setOrientation(int orientation) {
        this.orientation = orientation;
    }

    /**
     * 获取adapter
     *
     * @return CustomAdapterImp
     */
    public CustomAdapterImp getCustomAdapterImp() {
        return customAdapterImp;
    }

    public boolean isVerticalTop() {
        return isVerticalTop;
    }

    public void setVerticalTop(boolean isVerticalTop) {
        this.isVerticalTop = isVerticalTop;
    }

    public boolean isHorizontalRight() {
        return isHorizontalRight;
    }

    public void setHorizontalRight(boolean isHorizontalRight) {
        this.isHorizontalRight = isHorizontalRight;
    }

    public void setHorizontalLeft(boolean isHorizontalLeft) {
        this.isHorizontalLeft = isHorizontalLeft;
    }

    public void setVerticalBottom(boolean isVerticalBottom) {
        this.isVerticalBottom = isVerticalBottom;
    }

    public boolean isVerticalBottom() {
        return isVerticalBottom;
    }

    public boolean isHorizontalLeft() {
        return isHorizontalLeft;
    }

    /**
     * 循环体
     *
     * @param endIndex      位置
     * @param isStartOrStop 是否循环
     */
    public void sendRunnable(int endIndex, boolean isStartOrStop) {
        if (endOrStartRunning == null) {
            endOrStartRunning = new EndOrStartRunning(endIndex, isStartOrStop);
        } else {
            endOrStartRunning.endIndex = endIndex;
            endOrStartRunning.isStartOrStop = isStartOrStop;
        }
        cycle();
    }

    /**
     * 循环速度
     */
    private void cycle() {
        if (getOrientation() == Component.VERTICAL) {
            taskDispatcher.delayDispatch(endOrStartRunning, FIVE_INDEX);
        } else if (getOrientation() == Component.HORIZONTAL) {
            taskDispatcher.delayDispatch(endOrStartRunning, FIFTEEN_INDEX);
        }
    }

    /**
     * 是向前还是向后
     *
     * @param isBack 是否向后
     */
    public void setBack(boolean isBack) {
        this.isBack = isBack;
    }

    /**
     * 获取已经添加的中心位置
     *
     * @return int
     */
    public int getIndex() {
        if (getOrientation() == Component.VERTICAL) {
            return dataComponents.indexOf(addComponents.get(VISIBLE_MAX_NUM / INDEX));
        } else if (getOrientation() == Component.HORIZONTAL) {
            return dataComponents.indexOf(addComponents.get(VISIBLE_MAX_NUM / INDEX));
        }
        return 0;
    }

    /**
     * Runnable 接口
     */
    private class EndOrStartRunning implements Runnable {
        int endIndex;
        boolean isStartOrStop;

        EndOrStartRunning() {
        }

        private EndOrStartRunning(int endIndex, boolean isStartOrStop) {
            this.endIndex = endIndex;
            this.isStartOrStop = isStartOrStop;
        }

        @Override
        public void run() {
            if (isBack) {
                if (getOrientation() == Component.VERTICAL && isVerticalBottom) {
                    scrolledBottomVertical(endIndex, isStartOrStop);
                }

                if (getOrientation() == Component.VERTICAL && isVerticalTop) {
                    scrolledTopVertical(endIndex, isStartOrStop);
                }

                if (getOrientation() == Component.HORIZONTAL && isHorizontalLeft) {
                    if (isHorizontalBoundary) {
                        scrolledLeftHorizontal(endIndex, isStartOrStop);
                    } else {
                        scrolledRightHorizontal(endIndex, isStartOrStop);
                    }
                }
            } else {
                if (getOrientation() == Component.VERTICAL && isVerticalTop) {
                    scrolledTopVertical(endIndex, isStartOrStop);
                }

                if (getOrientation() == Component.VERTICAL && isVerticalBottom) {
                    scrolledBottomVertical(endIndex, isStartOrStop);
                }
                if (getOrientation() == Component.HORIZONTAL && isHorizontalRight) {
                    if (isHorizontalBoundary) {
                        scrolledLeftHorizontal(endIndex, isStartOrStop);
                    } else {
                        scrolledRightHorizontal(endIndex, isStartOrStop);
                    }
                }
            }
        }
    }

    public List<Component> getDataComponents() {
        return dataComponents;
    }

    public List<Component> getAddComponents() {
        return addComponents;
    }

    public int getVisibleMaxNum() {
        return VISIBLE_MAX_NUM;
    }

    /**
     * 设置边界
     *
     * @param isHorizontalBoundary 是否到边界
     */
    public void setHorizontalBoundary(boolean isHorizontalBoundary) {
        this.isHorizontalBoundary = isHorizontalBoundary;
    }
}
